#include <stdio.h>      // 用于输入输出操作，例如 printf, scanf
#include <stdlib.h>     // 用于动态内存分配，例如 malloc, free
#include <string.h>     // 用于字符串操作，例如 strncpy, strcmp


typedef struct Student {
    int id;                   // 学号
    char name[50];            // 姓名
    int age;                  // 年龄
    char gender[10];          // 性别
    float grade;              // 成绩
    char phone[15];           // 联系电话
    char address[100];        // 地址
    char major[50];           // 专业
    struct Student* next;     // 指向下一个学生，用于链表实现
} Student;


typedef struct {
    Student* head;            // 链表头指针，指向第一个学生
    int size;                 // 数据库中学生的数量
} Database;


#define MAX_NAME_LEN 50       // 姓名最大长度
#define MAX_PHONE_LEN 15      // 电话号码最大长度
#define MAX_ADDRESS_LEN 100   // 地址最大长度
#define MAX_MAJOR_LEN 50      // 专业最大长度


// 初始化数据库，将链表头置空，学生数量置为0
void initDatabase(Database* db) {
    if (db == NULL) {
        printf("Error: Database pointer is NULL.\n");
        return;
    }

    // 设置链表头指针为空
    db->head = NULL;

    // 初始化学生数量为0
    db->size = 0;

    // 打印初始化信息
    printf("Database initialized successfully.\n");
    printf("Initial student count: %d\n", db->size);
    printf("You can now add, delete, or search for student records.\n");

    // 提示用户接下来可执行的操作
    printf("Hint: Use the 'addStudent' function to add student records.\n");
}

// 添加学生信息到数据库中
void addStudent(Database* db, int id, const char* name, int age, const char* gender, float grade,
                const char* phone, const char* address, const char* major) {
    if (db == NULL || name == NULL || gender == NULL || phone == NULL || address == NULL || major == NULL) {
        printf("Error: Invalid input parameters.\n");
        return;
    }

    // 检查是否已经存在相同学号的学生
    Student* current = db->head;
    while (current != NULL) {
        if (current->id == id) {
            printf("Error: A student with ID %d already exists.\n", id);
            return;
        }
        current = current->next;
    }

    // 创建新学生节点
    Student* newStudent = (Student*)malloc(sizeof(Student));
    if (newStudent == NULL) {
        printf("Error: Memory allocation failed.\n");
        return;
    }

    // 初始化新学生的信息
    newStudent->id = id;
    strncpy(newStudent->name, name, MAX_NAME_LEN - 1);
    newStudent->name[MAX_NAME_LEN - 1] = '\0'; // 确保字符串以'\0'结尾
    newStudent->age = age;
    strncpy(newStudent->gender, gender, sizeof(newStudent->gender) - 1);
    newStudent->gender[sizeof(newStudent->gender) - 1] = '\0';
    newStudent->grade = grade;
    strncpy(newStudent->phone, phone, MAX_PHONE_LEN - 1);
    newStudent->phone[MAX_PHONE_LEN - 1] = '\0';
    strncpy(newStudent->address, address, MAX_ADDRESS_LEN - 1);
    newStudent->address[MAX_ADDRESS_LEN - 1] = '\0';
    strncpy(newStudent->major, major, MAX_MAJOR_LEN - 1);
    newStudent->major[MAX_MAJOR_LEN - 1] = '\0';
    newStudent->next = NULL;

    // 插入新节点到链表（按学号排序插入）
    Student* prev = NULL;
    current = db->head;
    while (current != NULL && current->id < id) {
        prev = current;
        current = current->next;
    }

    if (prev == NULL) {
        // 插入到链表头部
        newStudent->next = db->head;
        db->head = newStudent;
    } else {
        // 插入到链表中间或末尾
        prev->next = newStudent;
        newStudent->next = current;
    }

    // 更新数据库中的学生数量
    db->size++;

    // 打印添加成功的信息
    printf("Student added successfully:\n");
    printf("  ID: %d\n", id);
    printf("  Name: %s\n", name);
    printf("  Age: %d\n", age);
    printf("  Gender: %s\n", gender);
    printf("  Grade: %.2f\n", grade);
    printf("  Phone: %s\n", phone);
    printf("  Address: %s\n", address);
    printf("  Major: %s\n", major);
    printf("Current total students: %d\n", db->size);
}

// 删除学生信息（根据学号）
void deleteStudent(Database* db, int id) {
    if (db == NULL) {
        printf("Error: Database is not initialized.\n");
        return;
    }

    if (db->head == NULL) {
        printf("Error: No students in the database to delete.\n");
        return;
    }

    // 遍历链表找到目标学生
    Student* current = db->head;
    Student* previous = NULL;

    while (current != NULL) {
        if (current->id == id) {
            // 找到目标学生，执行删除操作
            if (previous == NULL) {
                // 删除头节点
                db->head = current->next;
            } else {
                // 删除中间或尾节点
                previous->next = current->next;
            }

            // 打印删除日志
            printf("Deleting student record:\n");
            printf("  ID: %d\n", current->id);
            printf("  Name: %s\n", current->name);
            printf("  Age: %d\n", current->age);
            printf("  Gender: %s\n", current->gender);
            printf("  Grade: %.2f\n", current->grade);
            printf("  Phone: %s\n", current->phone);
            printf("  Address: %s\n", current->address);
            printf("  Major: %s\n", current->major);

            // 释放内存并更新计数
            free(current);
            db->size--;
            printf("Student with ID %d deleted successfully.\n", id);
            printf("Current total students: %d\n", db->size);
            return;
        }

        // 继续遍历链表
        previous = current;
        current = current->next;
    }

    // 如果没有找到目标学生
    printf("Error: No student with ID %d found in the database.\n", id);
}


// 查找学生信息（根据学号）
Student* findStudentById(Database* db, int id) {
    if (db == NULL) {
        printf("Error: Database is not initialized.\n");
        return NULL;
    }

    if (db->head == NULL) {
        printf("Error: No students in the database to search.\n");
        return NULL;
    }

    // 遍历链表查找目标学生
    Student* current = db->head;
    while (current != NULL) {
        if (current->id == id) {
            // 找到目标学生，打印信息
            printf("Student found:\n");
            printf("  ID: %d\n", current->id);
            printf("  Name: %s\n", current->name);
            printf("  Age: %d\n", current->age);
            printf("  Gender: %s\n", current->gender);
            printf("  Grade: %.2f\n", current->grade);
            printf("  Phone: %s\n", current->phone);
            printf("  Address: %s\n", current->address);
            printf("  Major: %s\n", current->major);
            return current;
        }
        current = current->next;
    }

    // 没有找到目标学生
    printf("Error: No student with ID %d found in the database.\n", id);
    return NULL;
}


// 打印所有学生信息
void printAllStudents(Database* db) {
    if (db == NULL) {
        printf("Error: Database is not initialized.\n");
        return;
    }

    if (db->head == NULL) {
        printf("No students in the database to display.\n");
        return;
    }

    // 打印表格头部
    printf("\n===================== Student Records =====================\n");
    printf("| %-4s | %-20s | %-3s | %-6s | %-5s | %-13s | %-30s | %-15s |\n",
           "ID", "Name", "Age", "Gender", "Grade", "Phone", "Address", "Major");
    printf("=================================================================================================================\n");

    // 遍历链表打印每个学生的信息
    Student* current = db->head;
    int count = 0; // 学生计数器
    while (current != NULL) {
        printf("| %-4d | %-20s | %-3d | %-6s | %-5.2f | %-13s | %-30s | %-15s |\n",
               current->id, current->name, current->age, current->gender, current->grade,
               current->phone, current->address, current->major);
        current = current->next;
        count++;
    }

    // 打印表格尾部
    printf("=================================================================================================================\n");
    printf("Total students: %d\n", count);
    printf("==================================================== End of Records ====================================================\n");
}


// 按成绩范围筛选学生
void findStudentsByGrade(Database* db, float minGrade, float maxGrade) {
    if (db == NULL) {
        printf("Error: Database is not initialized.\n");
        return;
    }

    if (db->head == NULL) {
        printf("No students in the database to search.\n");
        return;
    }

    if (minGrade > maxGrade) {
        printf("Error: Invalid grade range. Minimum grade (%.2f) cannot be greater than maximum grade (%.2f).\n", minGrade, maxGrade);
        return;
    }

    // 打印筛选条件
    printf("\n===================== Grade Filter =====================\n");
    printf("Filtering students with grades between %.2f and %.2f...\n", minGrade, maxGrade);

    // 打印表格头部
    printf("\n===================== Matched Students =====================\n");
    printf("| %-4s | %-20s | %-3s | %-6s | %-5s | %-13s | %-30s | %-15s |\n",
           "ID", "Name", "Age", "Gender", "Grade", "Phone", "Address", "Major");
    printf("=================================================================================================================\n");

    // 遍历链表查找符合条件的学生
    Student* current = db->head;
    int count = 0; // 符合条件的学生计数器

    while (current != NULL) {
        if (current->grade >= minGrade && current->grade <= maxGrade) {
            // 打印学生信息
            printf("| %-4d | %-20s | %-3d | %-6s | %-5.2f | %-13s | %-30s | %-15s |\n",
                   current->id, current->name, current->age, current->gender, current->grade,
                   current->phone, current->address, current->major);
            count++;
        }
        current = current->next;
    }

    // 打印结果统计
    printf("=================================================================================================================\n");
    if (count == 0) {
        printf("No students found within the grade range %.2f - %.2f.\n", minGrade, maxGrade);
    } else {
        printf("Total matched students: %d\n", count);
    }
    printf("==================================================== End of Filtered Records ====================================================\n");
}



// 按专业筛选学生
void findStudentsByMajor(Database* db, const char* major) {
    if (db == NULL) {
        printf("Error: Database is not initialized.\n");
        return;
    }

    if (db->head == NULL) {
        printf("No students in the database to search.\n");
        return;
    }

    if (major == NULL || strlen(major) == 0) {
        printf("Error: Invalid major specified.\n");
        return;
    }

    // 打印筛选条件
    printf("\n===================== Major Filter =====================\n");
    printf("Filtering students in the major: %s\n", major);

    // 打印表格头部
    printf("\n===================== Matched Students =====================\n");
    printf("| %-4s | %-20s | %-3s | %-6s | %-5s | %-13s | %-30s | %-15s |\n",
           "ID", "Name", "Age", "Gender", "Grade", "Phone", "Address", "Major");
    printf("=================================================================================================================\n");

    // 遍历链表查找符合条件的学生
    Student* current = db->head;
    int count = 0; // 符合条件的学生计数器

    while (current != NULL) {
        if (strcmp(current->major, major) == 0) {
            // 打印学生信息
            printf("| %-4d | %-20s | %-3d | %-6s | %-5.2f | %-13s | %-30s | %-15s |\n",
                   current->id, current->name, current->age, current->gender, current->grade,
                   current->phone, current->address, current->major);
            count++;
        }
        current = current->next;
    }

    // 打印结果统计
    printf("=================================================================================================================\n");
    if (count == 0) {
        printf("No students found in the major: %s\n", major);
    } else {
        printf("Total matched students: %d\n", count);
    }
    printf("==================================================== End of Filtered Records ====================================================\n");
}

// 按性别筛选学生
void findStudentsByGender(Database* db, const char* gender) {
    if (db == NULL) {
        printf("Error: Database is not initialized.\n");
        return;
    }

    if (db->head == NULL) {
        printf("No students in the database to search.\n");
        return;
    }

    if (gender == NULL || strlen(gender) == 0) {
        printf("Error: Invalid gender specified.\n");
        return;
    }

    // 打印筛选条件
    printf("\n===================== Gender Filter =====================\n");
    printf("Filtering students with gender: %s\n", gender);

    // 打印表格头部
    printf("\n===================== Matched Students =====================\n");
    printf("| %-4s | %-20s | %-3s | %-6s | %-5s | %-13s | %-30s | %-15s |\n",
           "ID", "Name", "Age", "Gender", "Grade", "Phone", "Address", "Major");
    printf("=================================================================================================================\n");

    // 遍历链表查找符合条件的学生
    Student* current = db->head;
    int count = 0; // 符合条件的学生计数器

    while (current != NULL) {
        // 忽略大小写比较
        if (strcasecmp(current->gender, gender) == 0) {
            // 打印学生信息
            printf("| %-4d | %-20s | %-3d | %-6s | %-5.2f | %-13s | %-30s | %-15s |\n",
                   current->id, current->name, current->age, current->gender, current->grade,
                   current->phone, current->address, current->major);
            count++;
        }
        current = current->next;
    }

    // 打印结果统计
    printf("=================================================================================================================\n");
    if (count == 0) {
        printf("No students found with gender: %s\n", gender);
    } else {
        printf("Total matched students: %d\n", count);
    }
    printf("==================================================== End of Filtered Records ====================================================\n");
}

// 保存数据库到文件
void saveDatabaseToFile(Database* db, const char* filename) {
    if (db == NULL || filename == NULL) {
        printf("Error: Invalid database or filename.\n");
        return;
    }

    if (db->head == NULL) {
        printf("Warning: Database is empty. No data will be saved.\n");
        return;
    }

    // 打开文件以写入模式
    FILE* file = fopen(filename, "w");
    if (file == NULL) {
        printf("Error: Failed to open file '%s' for writing.\n", filename);
        return;
    }

    // 写入文件头部信息（标识文件格式）
    fprintf(file, "ID,Name,Age,Gender,Grade,Phone,Address,Major\n");

    // 遍历链表，将每个学生的信息写入文件
    Student* current = db->head;
    while (current != NULL) {
        fprintf(file, "%d,%s,%d,%s,%.2f,%s,%s,%s\n",
                current->id,
                current->name,
                current->age,
                current->gender,
                current->grade,
                current->phone,
                current->address,
                current->major);
        current = current->next;
    }

    // 关闭文件
    fclose(file);

    // 打印保存成功信息
    printf("Database successfully saved to file '%s'.\n", filename);
}


// 从文件加载数据库
void loadDatabaseFromFile(Database* db, const char* filename) {
    if (db == NULL || filename == NULL) {
        printf("Error: Invalid database or filename.\n");
        return;
    }

    // 打开文件以读取模式
    FILE* file = fopen(filename, "r");
    if (file == NULL) {
        printf("Error: Failed to open file '%s' for reading.\n", filename);
        return;
    }

    // 清空当前数据库（避免数据冲突）
    db->head = NULL;
    db->size = 0;

    // 读取文件头部（跳过第一行字段名）
    char buffer[512];
    if (fgets(buffer, sizeof(buffer), file) == NULL) {
        printf("Error: Failed to read the file header.\n");
        fclose(file);
        return;
    }

    // 逐行读取学生信息
    while (fgets(buffer, sizeof(buffer), file) != NULL) {
        int id, age;
        float grade;
        char name[50], gender[10], phone[15], address[100], major[50];

        // 使用 sscanf 解析 CSV 格式的每一行
        if (sscanf(buffer, "%d,%49[^,],%d,%9[^,],%f,%14[^,],%99[^,],%49[^\n]",
                   &id, name, &age, gender, &grade, phone, address, major) != 8) {
            printf("Warning: Skipping malformed line: %s", buffer);
            continue;
        }

        // 添加学生到数据库
        addStudent(db, id, name, age, gender, grade, phone, address, major);
    }

    // 关闭文件
    fclose(file);

    // 打印加载成功信息
    printf("Database successfully loaded from file '%s'.\n", filename);
    printf("Total students loaded: %d\n", db->size);
}

// 打印系统菜单
void printMenu() {
    printf("\n===================== Student Management System =====================\n");
    printf("Please select an option from the menu below:\n");
    printf("  1. Add a new student\n");
    printf("  2. Delete a student by ID\n");
    printf("  3. Update a student's information by ID\n");
    printf("  4. Find a student by ID\n");
    printf("  5. Display all students\n");
    printf("  6. Find students by grade range\n");
    printf("  7. Find students by major\n");
    printf("  8. Find students by gender\n");
    printf("  9. Save database to file\n");
    printf("  10. Load database from file\n");
    printf("  0. Exit the system\n");
    printf("=====================================================================\n");
    printf("Enter your choice: ");
}



// 打印单个学生的信息
void printStudentInfo(Student* student) {
    if (student == NULL) {
        printf("Error: Student not found.\n");
        return;
    }

    printf("\n===================== Student Information =====================\n");
    printf("  ID: %d\n", student->id);
    printf("  Name: %s\n", student->name);
    printf("  Age: %d\n", student->age);
    printf("  Gender: %s\n", student->gender);
    printf("  Grade: %.2f\n", student->grade);
    printf("  Phone: %s\n", student->phone);
    printf("  Address: %s\n", student->address);
    printf("  Major: %s\n", student->major);
    printf("===============================================================\n");
}


void updateStudent(Database* db, int id, const char* name, int age, const char* gender, float grade,
                   const char* phone, const char* address, const char* major) {
    if (db == NULL) {
        printf("Error: Database is not initialized.\n");
        return;
    }

    Student* student = findStudentById(db, id);
    if (student == NULL) {
        printf("Error: No student found with ID %d.\n", id);
        return;
    }

    // 更新学生信息
    strncpy(student->name, name, sizeof(student->name) - 1);
    student->name[sizeof(student->name) - 1] = '\0'; // 确保字符串以'\0'结尾
    student->age = age;
    strncpy(student->gender, gender, sizeof(student->gender) - 1);
    student->gender[sizeof(student->gender) - 1] = '\0';
    student->grade = grade;
    strncpy(student->phone, phone, sizeof(student->phone) - 1);
    student->phone[sizeof(student->phone) - 1] = '\0';
    strncpy(student->address, address, sizeof(student->address) - 1);
    student->address[sizeof(student->address) - 1] = '\0';
    strncpy(student->major, major, sizeof(student->major) - 1);
    student->major[sizeof(student->major) - 1] = '\0';

    printf("Student with ID %d has been updated successfully.\n", id);
}

void clearDatabase(Database* db) {
    if (db == NULL) {
        printf("Error: Database is not initialized.\n");
        return;
    }

    Student* current = db->head;
    while (current != NULL) {
        Student* temp = current;
        current = current->next;
        free(temp);
    }

    db->head = NULL;
    db->size = 0;

    printf("Database has been cleared. All records have been deleted.\n");
}


int main() {
    // 初始化数据库
    Database db;
    initDatabase(&db);

    int choice;   // 用户选择的菜单选项
    int id, age;
    float grade;
    char name[50], gender[10], phone[15], address[100], major[50];
    char filename[100];

    while (1) {
        // 打印菜单并获取用户选择
        printMenu();
        scanf("%d", &choice);

        switch (choice) {
            case 1: // 添加学生
                printf("Enter student details:\n");
                printf("ID: "); scanf("%d", &id);
                printf("Name: "); scanf(" %[^\n]", name);
                printf("Age: "); scanf("%d", &age);
                printf("Gender: "); scanf(" %[^\n]", gender);
                printf("Grade: "); scanf("%f", &grade);
                printf("Phone: "); scanf(" %[^\n]", phone);
                printf("Address: "); scanf(" %[^\n]", address);
                printf("Major: "); scanf(" %[^\n]", major);
                addStudent(&db, id, name, age, gender, grade, phone, address, major);
                break;

            case 2: // 删除学生
                printf("Enter student ID to delete: ");
                scanf("%d", &id);
                deleteStudent(&db, id);
                break;

            case 3: // 更新学生信息
                printf("Enter student ID to update: ");
                scanf("%d", &id);
                printf("Enter updated details:\n");
                printf("Name: "); scanf(" %[^\n]", name);
                printf("Age: "); scanf("%d", &age);
                printf("Gender: "); scanf(" %[^\n]", gender);
                printf("Grade: "); scanf("%f", &grade);
                printf("Phone: "); scanf(" %[^\n]", phone);
                printf("Address: "); scanf(" %[^\n]", address);
                printf("Major: "); scanf(" %[^\n]", major);
                updateStudent(&db, id, name, age, gender, grade, phone, address, major);
                break;

            case 4: // 查找学生信息
                printf("Enter student ID to find: ");
                scanf("%d", &id);
                printStudentInfo(findStudentById(&db, id));
                break;

            case 5: // 打印所有学生信息
                printAllStudents(&db);
                break;

            case 6: // 按成绩范围筛选学生
                printf("Enter grade range (min max): ");
                float minGrade, maxGrade;
                scanf("%f %f", &minGrade, &maxGrade);
                findStudentsByGrade(&db, minGrade, maxGrade);
                break;

            case 7: // 按专业筛选学生
                printf("Enter major to filter: ");
                scanf(" %[^\n]", major);
                findStudentsByMajor(&db, major);
                break;

            case 8: // 按性别筛选学生
                printf("Enter gender to filter: ");
                scanf(" %[^\n]", gender);
                findStudentsByGender(&db, gender);
                break;

            case 9: // 保存数据库到文件
                printf("Enter filename to save database: ");
                scanf(" %[^\n]", filename);
                saveDatabaseToFile(&db, filename);
                break;

            case 10: // 从文件加载数据库
                printf("Enter filename to load database: ");
                scanf(" %[^\n]", filename);
                loadDatabaseFromFile(&db, filename);
                break;

            case 0: // 退出系统
                printf("Exiting the system. Goodbye!\n");
                clearDatabase(&db); // 清空数据库，释放内存
                return 0;

            default: // 无效输入
                printf("Invalid choice. Please try again.\n");
        }
    }
}
